home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / vol_400 / 430_01 / m68kdis / mac / rf.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-12-29  |  8.9 KB  |  366 lines

  1. /*
  2.  *                 Author:  Christopher G. Phillips
  3.  *              Copyright (C) 1994 All Rights Reserved
  4.  *
  5.  *                              NOTICE
  6.  *
  7.  * Permission to use, copy, modify, and distribute this software and
  8.  * its documentation for any purpose and without fee is hereby granted
  9.  * provided that the above copyright notice appear in all copies and
  10.  * that both the copyright notice and this permission notice appear in
  11.  * supporting documentation.
  12.  *
  13.  * The author makes no representations about the suitability of this
  14.  * software for any purpose.  This software is provided ``as is''
  15.  * without express or implied warranty.
  16.  */
  17.  
  18. #include <stdio.h>
  19. #include <stdlib.h>
  20. #include <limits.h>
  21. #include <sys/types.h>
  22. #include <netinet/in.h>
  23.  
  24. #if CHAR_BIT == 8
  25. #if UCHAR_MAX == 255U
  26. typedef unsigned char    u8bit_t;
  27. #endif
  28. #else
  29. typedef no_8_bit_type    u8bit_t;    /* error */
  30. #endif
  31. #if USHRT_MAX == 65535U
  32. typedef unsigned short    u16bit_t;
  33. typedef short        s16bit_t;
  34. #else
  35. typedef no_16_bit_type    u16bit_t;    /* error */
  36. #endif
  37. #if UINT_MAX == 4294967295U
  38. typedef unsigned int    u32bit_t;
  39. typedef int        s32bit_t;
  40. #else
  41. typedef no_32_bit_type    u32bit_t;    /* error */
  42. #endif
  43.  
  44. struct header {
  45.     u32bit_t    data_offset;    /* offset from beginning
  46.                        of resource file to resource data */
  47.     u32bit_t    map_offset;    /* offset from beginning
  48.                        of resource file to resource map */
  49.     u32bit_t    data_length;    /* Length of resource data */
  50.     u32bit_t    map_length;    /* Length of resource map */
  51. };
  52. #define HEADERSIZE    16
  53.  
  54. struct map {
  55.     /*
  56.      * First there are 22 bytes of zeros:
  57.      *
  58.      * 16 bytes: reserved for copy of resource header
  59.      *  4 bytes: reserved for handle to next resource map to be searched
  60.      *  2 bytes: reserved for file reference number
  61.      */
  62.     char        header[16];
  63.     char        handle[4];
  64.     char        reference_number[2];
  65.     u16bit_t    attributes;        /* resource file attributes */
  66.     u16bit_t    typelist_offset;    /* offset from beginning of
  67.                            resource map to type list */
  68.     u16bit_t    namelist_offset;    /* offset from beginning of
  69.                            resource map to resource
  70.                            name list */
  71. };
  72. #define MAPSIZE        28
  73.  
  74. /*
  75.  * Resource file attributes
  76.  */
  77. #define MAP_READ_ONLY    0x80    /* set if file is read-only */
  78. #define MAP_COMPACT    0x40    /* set to compact file on update */
  79. #define MAP_CHANGED    0x20    /* set to write map on update */
  80.  
  81. struct type {
  82.     char        type[4];    /* resource type */
  83.     u16bit_t    nresources;    /* number of resources of this type
  84.                        in the map (NOT minus 1) */
  85.     u16bit_t    offset;        /* offset from beginning of type list
  86.                        to reference list for resources
  87.                        of this type */
  88. };
  89. #define TYPESIZE    8
  90.  
  91. struct resource {
  92.     u16bit_t    ID;        /* resource ID */
  93.     s16bit_t    name_length_offset;
  94.                     /* offset from beginning of resource
  95.                        name list to length of resource name
  96.                        or -1 if none */
  97.     char        attributes;    /* resource attributes */
  98.     u32bit_t    data_length_offset;
  99.                     /* offset from beginning of resource
  100.                        data to length of data for this
  101.                        resource */
  102.     /* NOTE: length_offset is really only 24 bits */
  103. };
  104. #define RESOURCESIZE    12
  105.  
  106. /*
  107.  * Resource attributes
  108.  */
  109. #define RES_SYS_HEAP    0x40    /* set if read into system heap */
  110. #define RES_PURGEABLE    0x20    /* set if purgeable */
  111. #define RES_LOCKED    0x10    /* set if locked */
  112. #define RES_PROTECTED    0x08    /* set if protected */
  113. #define RES_PRELOAD    0x04    /* set if to be preloaded */
  114. #define RES_CHANGED    0x02    /* set if to be written to resource file */
  115.  
  116. /*
  117.  * #defines specific to this application
  118.  */
  119. #define FREAD(nbytes, s, fp)    if (fread(buf, 1, nbytes, fp) != nbytes) \
  120.                     error("read from " s, fp)
  121. #define FREADM(nbytes, s, fp)    if (fread(mbuf, 1, nbytes, fp) != nbytes) \
  122.                     error("read from " s, fp)
  123. #define FSEEK(offset, s, fp)    if (fseek(fp, offset, SEEK_SET) == -1) \
  124.                     error("seek to " s, fp)
  125.  
  126. #define CVT32(a, index)        a = ntohl(*(u32bit_t *)&buf[index])
  127. #define CVT16(a, index)        a = ntohs(*(u16bit_t *)&buf[index])
  128.  
  129. void
  130. od(unsigned char *buf, size_t length)
  131. {
  132.     size_t        nlines = (length + 15) / 16;
  133.     size_t        line;
  134.     size_t        left = length;
  135.     short        charnum;
  136.  
  137.     for (line = 0; line < nlines; line++) {
  138.         for (charnum = 0; charnum < 16 && left; charnum++, left--) {
  139.             if (charnum && (charnum % 2) == 0)
  140.                 putchar(' ');
  141.             printf("%02x", buf[length - left]);
  142.         }
  143.         putchar('\n');
  144.     }
  145. }
  146.  
  147. void
  148. pstr(const unsigned char *s, int length)
  149. {
  150.     while (length--) {
  151.         if (isprint(*s))
  152.             putchar(*s);
  153.         else
  154.             printf("\\%0o", *s);
  155.         s++;
  156.     }
  157. }
  158.  
  159. void
  160. error(char *s, FILE *fp)
  161. {
  162.     if (fp && ferror(fp))
  163.         perror(s);
  164.     else
  165.         fprintf(stderr, "Bad file format: %s\n", s);
  166.  
  167.     exit(1);
  168. }
  169.  
  170. void
  171. printrf(FILE *fp)
  172. {
  173.     unsigned char    buf[BUFSIZ];
  174.     int        i;
  175.     int        j;
  176.     long        typelist_offset;
  177.     long        namelist_offset;
  178.     long        offset;
  179.  
  180.     struct header    header;
  181.     char        system_use[112];
  182.     char        app_data[128];
  183.     struct map    map;
  184.     u16bit_t    ntypes;
  185.     struct type    type;
  186.     struct resource    resource;
  187.     u8bit_t        name_length;
  188.     u32bit_t    data_length;
  189.     unsigned char    *mbuf = NULL;
  190.     long        type_offset;
  191.     long        resource_offset;
  192.  
  193.     /*
  194.      * Read the header.
  195.      */
  196.     FREAD(HEADERSIZE, "header", fp);
  197.     CVT32(header.data_offset, 0);
  198.     CVT32(header.map_offset, 4);
  199.     CVT32(header.data_length, 8);
  200.     CVT32(header.map_length, 12);
  201.  
  202.     /*
  203.      * The header is followed by 112 bytes reserved
  204.      * for system use and then 128 bytes available
  205.      * for application data.
  206.      */
  207.     if (fread(system_use, 1, sizeof system_use, fp) != sizeof system_use)
  208.         error("system_use", fp);
  209.     if (fread(app_data, 1, sizeof app_data, fp) != sizeof app_data)
  210.         error("app_data", fp);
  211.  
  212.     /*
  213.      * Read the resource map.
  214.      */
  215.     FSEEK(header.map_offset, "map", fp);
  216.     FREAD(MAPSIZE, "map", fp);
  217.     CVT16(map.attributes, 22);
  218.     CVT16(map.typelist_offset, 24);
  219.     typelist_offset = header.map_offset + map.typelist_offset;
  220.     CVT16(map.namelist_offset, 26);
  221.     namelist_offset = header.map_offset + map.namelist_offset;
  222.  
  223.     printf("Resource file attributes:");
  224.     if (map.attributes == 0)
  225.         printf(" none");
  226.     else {
  227. #define DOATTR(attr, string)    if (map.attributes & attr) { \
  228.                     printf(" " string); \
  229.                     map.attributes &= ~attr; \
  230.                 }
  231.         DOATTR(MAP_READ_ONLY, "read_only")
  232.         DOATTR(MAP_COMPACT, "compact")
  233.         DOATTR(MAP_CHANGED, "changed")
  234. #undef DOATTR
  235.     }
  236.     if (map.attributes)
  237.         printf(" UNKNOWN");
  238.     printf("\n\n");
  239.  
  240.     /*
  241.      * The type list contains
  242.      *
  243.      * 2 bytes: number of resource types in the map minus 1
  244.      * 
  245.      * followed immediately by the types.
  246.      */
  247.     FSEEK(typelist_offset, "type list", fp);
  248.     FREAD(2, "type list", fp);
  249.     CVT16(ntypes, 0);
  250.     ntypes++;
  251.  
  252.     /*
  253.      * Read the types.
  254.      */
  255.     type_offset = typelist_offset + 2;
  256.     for (i = 0; i < ntypes; i++, type_offset += TYPESIZE) {
  257.         FSEEK(type_offset, "type", fp);
  258.         FREAD(TYPESIZE, "type", fp);
  259.         strncpy(type.type, buf, sizeof type.type);
  260.         CVT16(type.nresources, 4);
  261.         type.nresources++;
  262.         CVT16(type.offset, 6);
  263.  
  264.         if (i)
  265.             putchar('\n');
  266.         printf("Resource type: \"%4.4s\"\n", type.type);
  267.         printf("\n");
  268.  
  269.         /*
  270.          * Read the resources.
  271.          */
  272.         resource_offset = typelist_offset + type.offset;
  273.         for (j = 0; j < type.nresources; j++,
  274.           resource_offset += RESOURCESIZE) {
  275.             FSEEK(resource_offset, "resource", fp);
  276.             FREAD(RESOURCESIZE, "resource", fp);
  277.             CVT16(resource.ID, 0);
  278.             CVT16(resource.name_length_offset, 2);
  279.             resource.attributes = buf[4];
  280.             CVT32(resource.data_length_offset, 4);
  281.             resource.data_length_offset &= 0x00ffffff;
  282.  
  283.             if (j)
  284.                 putchar('\n');
  285.             printf("ID %d\n", resource.ID);
  286.             printf("Attributes:");
  287.             if (resource.attributes == 0)
  288.                 printf(" none");
  289.             else {
  290. #define DOATTR(attr, string)    if (resource.attributes & attr) { \
  291.                     printf(" " string); \
  292.                     resource.attributes &= ~attr; \
  293.                 }
  294.                 DOATTR(RES_SYS_HEAP, "sys_head")
  295.                 DOATTR(RES_PURGEABLE, "purgeable")
  296.                 DOATTR(RES_LOCKED, "locked")
  297.                 DOATTR(RES_PROTECTED, "protected")
  298.                 DOATTR(RES_PRELOAD, "preload")
  299.                 DOATTR(RES_CHANGED, "changed")
  300. #undef DOATTR
  301.             }
  302.             if (resource.attributes)
  303.                 printf(" UNKNOWN");
  304.             putchar('\n');
  305.  
  306.             if (resource.name_length_offset != -1) {
  307.                 /*
  308.                  * Read resource name.
  309.                  */
  310.                 FSEEK(namelist_offset
  311.                   + resource.name_length_offset,
  312.                   "resource name", fp);
  313.                 FREAD(1, "resource name length", fp);
  314.                 name_length = buf[0];
  315.                 FREAD(name_length, "actual resource name", fp);
  316.                 printf("Name length: %d\n", name_length);
  317.                 printf("Name: \"");
  318.                 pstr(buf, name_length);
  319.                 printf("\"\n");
  320.             } else
  321.                 printf("No name\n");
  322.     
  323.             /*
  324.              * Read resource data.
  325.              */
  326.             FSEEK(header.data_offset + resource.data_length_offset,
  327.               "resource data", fp);
  328.             FREAD(4, "resource data length", fp);
  329.             CVT32(data_length, 0);
  330.             if (data_length
  331.               && (mbuf = realloc(mbuf, data_length)) == NULL) {
  332.                 perror("realloc");
  333.                 exit(1);
  334.             }
  335.             if (data_length)
  336.                 printf("Bytes %lx to %lx\n",
  337.                   (long)(header.data_offset
  338.                   + resource.data_length_offset) + 4,
  339.                   (long)(data_length + header.data_offset
  340.                   + resource.data_length_offset + 4 - 1));
  341.             FREADM(data_length, "actual resource data", fp);
  342.             od(mbuf, data_length);
  343.         }
  344.     }
  345. }
  346.  
  347. int
  348. main(int argc, char **argv)
  349. {
  350.     FILE    *fp;
  351.  
  352.     if (--argc) {
  353.         if ((fp = fopen(argv[1], "r")) == NULL) {
  354.             perror(argv[1]);
  355.             exit(1);
  356.         }
  357.     } else {
  358.         fprintf(stderr, "Usage: %s filename\n", argv[0]);
  359.         exit(2);
  360.     }
  361.  
  362.     printrf(fp);
  363.  
  364.     exit(0);
  365. }
  366.